﻿using System;
using System.Data;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.Office.Server.UserProfiles;

using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.SharePoint.Common.ServiceLocation;
using Microsoft.Practices.SharePoint.Common.Logging;

namespace EFSPWebParts
{
    public class DataTableWrapper
    {
        private DataTable _dt = new DataTable();

        public static void MyTraceToDeveloper(ILogger _logger, string strMessage)
        {
#if DEBUG
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.TraceToDeveloper(string.Format("EFSPWebParts.DataTableWrapper - {0}", strMessage), TraceSeverity.Monitorable);
            });
#endif
        }

        public DataTableWrapper(DataTable dt)
        {
            _dt = dt;
        }

        public DataTable GetTable(string SortExpression)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();

            MyTraceToDeveloper(_logger, string.Format("GetTable(), SortExpression={0}", SortExpression));

            if (string.IsNullOrEmpty(SortExpression) == false)
            {
                _dt.DefaultView.Sort = SortExpression;
            }

            DataTable objDest = _dt.DefaultView.ToTable();
            //foreach (DataColumn objDataColumnTmp in objDest.Columns)
            //{
            //    MyTraceToDeveloper(_logger, string.Format("GetTable(), objDest.TableColumnName={0}, DataType={1}", objDataColumnTmp.ColumnName, objDataColumnTmp.DataType));
            //}

            return objDest;
        }
    }

    public partial class SiteDataQueryUserControl : UserControl
    {
        #region common functions

        public static void MyTraceToDeveloper(ILogger _logger, string strMessage)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.TraceToDeveloper(string.Format("EFSPWebParts.SiteDataQueryUserControl - {0}", strMessage), TraceSeverity.Monitorable);
            });
        }

        public static void MyLogToOperations(ILogger _logger, string strMessage)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.LogToOperations(string.Format("EFSPWebParts.SiteDataQueryUserControl - {0}", strMessage), 0, EventSeverity.ErrorCritical);
            });
        }

        public static void MyLogToOperations(ILogger _logger, Exception ex)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.LogToOperations(ex, @"EFSPWebParts.SiteDataQueryUserControl");
            });
        }
        #endregion

        #region member variables

        public const string ColumnNameFileName = @"FileName";
        public const string ColumnNameFileUrl = @"FileUrl";
        public const string ColumnNameFileSize = @"FileSize";
        public const string ColumnNameModified = @"Modified";
        public const string ColumnNameModifiedBy = @"ModifiedBy";
        public const string ColumnNameModifiedByUrl = @"ModifiedByUrl";
        public const long lMBsize = 1024 * 1024;
        public const long lKBsize = 1024;

        //private SPGridView grid;
        //private DataView oView;

        DataTable sourceDataTable;
        private DataTableWrapper myDataTable;

        public SiteDataQuery.enumSearchWebsScope _WebsScope = SiteDataQuery.enumSearchWebsScope.Recursive;
        public SiteDataQuery.enumListBaseType _ListBaseType = SiteDataQuery.enumListBaseType.GenericList;
        public bool _UseAccessibleHeader = false;
        public bool _AllowSorting = true;
        public bool _AllowFiltering = true;
        public string _FilterDataFields = string.Empty;

        public bool _AllowPaging = true;
        public int _PageSize = 3;

        public Color _RowStyle_BackColor = Color.White;
        public Color _AlternatingRowStyle_BackColor = Color.White;

        public uint _QueryRowLimit = uint.MaxValue;
        public string _CAMLQuery = string.Empty;
        public string _CAMLQueryOrderBy = string.Empty;

        public bool _ColumnNameFileName = true;
        public bool _ColumnNameFileNameFiltering = true;
        public bool _ColumnNameModifiedBy = true;
        public bool _ColumnNameModifiedByFiltering = true;
        public bool _ColumnNameModified = true;
        public bool _ColumnNameModifiedFiltering = true;
        public bool _ColumnNameFileSize = true;
        public bool _ColumnNameFileSizeFiltering = true;

        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();

            if (gView == null)
            {
                MyLogToOperations(_logger, string.Format("Page_Load(), Exception: gView is null"));
                return;
            }

            RenderContents();
        }

        public void ds_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
        {
            myDataTable = new DataTableWrapper(sourceDataTable);
            e.ObjectInstance = myDataTable;
        }

        public void ds_Filtering(object sender, ObjectDataSourceFilteringEventArgs e)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();

            MyTraceToDeveloper(_logger, string.Format("ds_Filtering(), ((ObjectDataSourceView)sender).FilterExpression={0}", ((ObjectDataSourceView)sender).FilterExpression));

            ViewState["FilterExpression"] = ((ObjectDataSourceView)sender).FilterExpression;
        }

        protected sealed override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            if (Context.Request.Form["__EVENTARGUMENT"] != null &&
                 Context.Request.Form["__EVENTARGUMENT"].EndsWith("__ClearFilter__"))
            {
                // Clear FilterExpression
                ViewState.Remove("FilterExpression");
            }
        }

        public string getFilterDataFields()
        {   //  string.Format(@"{0},{1},,", ColumnNameFileName, ColumnNameModifiedBy);
            string strValue = string.Empty;
            if (_ColumnNameFileName)
            {
                strValue += @",";
                if (_ColumnNameFileNameFiltering)
                    strValue += ColumnNameFileName;
            }
            if (_ColumnNameModifiedBy)
            {
                strValue += @",";
                if (_ColumnNameModifiedByFiltering)
                    strValue += ColumnNameModifiedBy;
            }
            if (_ColumnNameModified)
            {
                strValue += @",";
                if (_ColumnNameModifiedFiltering)
                    strValue += ColumnNameModified;
            }
            if (_ColumnNameFileSize)
            {
                strValue += @",";
                if (_ColumnNameFileSizeFiltering)
                    strValue += ColumnNameFileSize;
            }

            return strValue.TrimStart(',');
        }

        public void configureGridViewFilter()
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();
            MyTraceToDeveloper(_logger, string.Format("configureGridViewFilter(), gView.AllowFiltering={0}", gView.AllowFiltering));

            if (gView.AllowFiltering == false)
            {
                gView.FilterDataFields = string.Empty;
                gView.FilteredDataSourcePropertyName = string.Empty;
                gView.FilteredDataSourcePropertyFormat = string.Empty;
                return;
            }

            //gView.FilterDataFields = string.Format(@"{0},{1},,", ColumnNameFileName, ColumnNameModifiedBy);
            gView.FilterDataFields = getFilterDataFields();
            gView.FilteredDataSourcePropertyName = "FilterExpression";
            gView.FilteredDataSourcePropertyFormat = "{1} like '{0}'";

            //foreach (DataControlField objDataControlField in gView.Columns)
            //{
            //    MyTraceToDeveloper(_logger, string.Format("configureGridViewFilter(), objDataControlField.HeaderText={0}", objDataControlField.HeaderText));
            //}
        }

        public void initGridView()
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();

            HyperLinkField objHyperLinkField = null;
            BoundField objBoundField = null;

            if (gView == null)
            {
                MyLogToOperations(_logger, string.Format("initGridView(), Exception: gView is null"));
                return;
            }

            try
            {
                if (!Page.IsPostBack || gView.Columns.Count < 1)
                {
                    gView.UseAccessibleHeader = this._UseAccessibleHeader;
                    //gView.UseAccessibleHeader = true;
                    gView.AllowFiltering = this._AllowFiltering;
                    gView.AllowPaging = this._AllowPaging;
                    gView.AllowSorting = this._AllowSorting;

                    if (this._AllowPaging == true)
                        gView.PageSize = this._PageSize;

                    gView.RowStyle.BackColor = this._RowStyle_BackColor;
                    gView.AlternatingRowStyle.BackColor = this._AlternatingRowStyle_BackColor;

                    // sample:  http://pdsha02:82/test/Shared%20Documents/Logo.NSW.ACT.BW.gif
                    if (_ColumnNameFileName)
                    {
                        objHyperLinkField = new HyperLinkField();
                        objHyperLinkField.DataTextField = ColumnNameFileName;
                        objHyperLinkField.DataNavigateUrlFields = new string[] { ColumnNameFileUrl };
                        objHyperLinkField.DataNavigateUrlFormatString = @"{0}";
                        objHyperLinkField.HeaderText = "File Name";
                        objHyperLinkField.SortExpression = ColumnNameFileName;
                        gView.Columns.Add(objHyperLinkField);
                    }

                    if (_ColumnNameModifiedBy)
                    {
                        objHyperLinkField = new HyperLinkField();
                        objHyperLinkField.DataTextField = ColumnNameModifiedBy;
                        objHyperLinkField.DataNavigateUrlFields = new string[] { ColumnNameModifiedByUrl };
                        objHyperLinkField.DataNavigateUrlFormatString = @"{0}";
                        objHyperLinkField.HeaderText = "Modified By";
                        objHyperLinkField.SortExpression = ColumnNameModifiedBy;
                        gView.Columns.Add(objHyperLinkField);
                    }

                    if (_ColumnNameModified)
                    {
                        objBoundField = new BoundField();
                        objBoundField.HeaderText = @"Modified";
                        objBoundField.DataField = ColumnNameModified;
                        objBoundField.SortExpression = ColumnNameModified;
                        gView.Columns.Add(objBoundField);
                    }

                    if (_ColumnNameFileSize)
                    {
                        objBoundField = new BoundField();
                        objBoundField.HeaderText = @"File Size (KB)";
                        objBoundField.DataField = ColumnNameFileSize;
                        objBoundField.DataFormatString = @"{0:F2}";
                        objBoundField.SortExpression = ColumnNameFileSize;
                        gView.Columns.Add(objBoundField);
                    }
                }
            }
            catch (Exception ex)
            {
                MyLogToOperations(_logger, ex);

                throw;
            }
        }

        public static DataTable ConvertDataTable(SPSite objSPSite, DataTable objDataTableSource)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();

            MyTraceToDeveloper(_logger, string.Format("dtSource.Rows.Count={0}", objDataTableSource.Rows.Count));

            DataTable dtDestination = new DataTable();
            DataColumn objDataColumn = null;
            DataRow objDataRow = null;

            string strModifiedId = SPBuiltInFieldId.Modified.ToString("B");
            string strFileUrlId = SPBuiltInFieldId.URL.ToString("B");
            Guid objGuidWebId = Guid.Empty;
            Guid objGuidListId = Guid.Empty;
            int ItemId = int.MinValue;

            SPServiceContext objSPServiceContext = null;
            UserProfileManager objUserProfileManager = null;

            try
            {
                //foreach (DataColumn objDataColumnTmp in objDataTableSource.Columns)
                //{
                //    MyTraceToDeveloper(_logger, string.Format("ConvertDataTable(), objDataTableSource.ColumnName={0}, DataType={1}", objDataColumnTmp.ColumnName, objDataColumnTmp.DataType));
                //}

                //return null;

                objDataColumn = new DataColumn(ColumnNameFileName, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameModifiedBy, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameFileUrl, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameFileSize, System.Type.GetType("System.Decimal"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameModified, System.Type.GetType("System.DateTime"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameModifiedByUrl, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);

                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    objSPServiceContext = SPServiceContext.GetContext(objSPSite);
                    objUserProfileManager = new UserProfileManager(objSPServiceContext);

                    foreach (DataRow objDataRowSource in objDataTableSource.Rows)
                    {
                        objGuidWebId = new Guid(Convert.ToString(objDataRowSource["WebId"]));
                        objGuidListId = new Guid(Convert.ToString(objDataRowSource["ListId"]));
                        ItemId = Convert.ToInt32(objDataRowSource["ID"]);
                        using (SPWeb objSPWeb = objSPSite.OpenWeb(objGuidWebId))
                        {
                            SPListItem objSPListItem = objSPWeb.Lists[objGuidListId].GetItemById(ItemId);
                            objDataRow = dtDestination.Rows.Add();
                            objDataRow[ColumnNameFileName] = objSPListItem.File.Name;
                            objDataRow[ColumnNameFileUrl] = string.Format(@"{0}/{1}", objSPWeb.Url, objSPListItem.File.Url);
                            //objDataRow[ColumnNameFileSize] = ((decimal)objSPListItem.File.Length) / lMBsize;
                            objDataRow[ColumnNameFileSize] = Math.Round(Convert.ToDecimal(objSPListItem.File.Length) / lKBsize, 2);
                            objDataRow[ColumnNameModified] = objSPListItem.File.TimeLastModified;
                            objDataRow[ColumnNameModifiedBy] = objSPListItem.File.ModifiedBy.Name;
                            //if (objSPListItem.File.ModifiedBy.LoginName.Equals(@"sharepoint\system", StringComparison.InvariantCultureIgnoreCase))
                            if (objUserProfileManager.UserExists(objSPListItem.File.ModifiedBy.LoginName) == false)
                            {
                                //  http://pdsha02:82/test/_layouts/userdisp.aspx?ID=1073741823
                                objDataRow[ColumnNameModifiedByUrl] = string.Format(@"{0}/_layouts/userdisp.aspx?ID={1}", objSPWeb.Url, objSPListItem.File.ModifiedBy.ID);
                            }
                            else
                            {
                                //  http://SharePointServer:800/Person.aspx?accountname=DomainName%5CUserLoginName

                                UserProfile p = objUserProfileManager.GetUserProfile(objSPListItem.File.ModifiedBy.LoginName);
                                objDataRow[ColumnNameModifiedByUrl] = p.PersonalUrl;

                                objDataRow[ColumnNameModifiedByUrl] = string.Format(@"{0}/Person.aspx?accountname={1}", objUserProfileManager.MySiteHostUrl, objSPListItem.File.ModifiedBy.LoginName);
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                MyLogToOperations(_logger, ex);

                throw;
            }

            //foreach (DataColumn objDataColumnTmp in dtDestination.Columns)
            //{
            //    MyTraceToDeveloper(_logger, string.Format("ConvertDataTable(), dtDestination.ColumnName={0}, DataType={1}", objDataColumnTmp.ColumnName, objDataColumnTmp.DataType));
            //}
            return dtDestination;
        }

        //protected override void RenderContents(HtmlTextWriter writer)
        public void RenderContents()
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();
            MyTraceToDeveloper(_logger, string.Format("RenderContents(), SPContext.Current.Web.Url={0}", SPContext.Current.Web.Url));

            //string strLinkFilenameId = SPBuiltInFieldId.LinkFilename.ToString("B");
            //string strEditorId = SPBuiltInFieldId.Editor.ToString("B");
            string strModifiedId = SPBuiltInFieldId.Modified.ToString("B");
            string strFileUrlId = SPBuiltInFieldId.URL.ToString("B");

            SPWeb web = SPContext.Current.Web;
            SPSiteDataQuery query = new SPSiteDataQuery();

            //query Document library, http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsitedataquery.lists.aspx
            query.Webs = string.Format(@"<Webs Scope='{0}' />", _WebsScope.ToString());
            query.Lists = string.Format(@"<Lists BaseType='{0}' />", (int)_ListBaseType);

            //query.ViewFields = string.Format("<FieldRef Name='{0}' />", strModifiedId);
            //query.ViewFields += string.Format("<FieldRef Name='{0}' />", strFileUrlId);

            if (string.IsNullOrEmpty(_CAMLQuery))
            {
                query.Query = @"<Where><Gt>" +
                    "<FieldRef Name='ID' /><Value Type='Counter'>0</Value>" +
                    "</Gt></Where>";
            }
            else
            {
                query.Query = _CAMLQuery;
            }

            if (string.IsNullOrEmpty(_CAMLQueryOrderBy))
            {
                query.Query += string.Format(@"<OrderBy Ascending='FALSE'><FieldRef Name='{0}' /></OrderBy>", strModifiedId);
            }
            else
            {
                query.Query = _CAMLQueryOrderBy;
            }

            query.RowLimit = _QueryRowLimit;

            try
            {
                DataTable dtOriginal = SPContext.Current.Web.GetSiteData(query);
                sourceDataTable = ConvertDataTable(SPContext.Current.Site, dtOriginal);

                if (sourceDataTable == null)
                    return;

                initGridView();

                MyTraceToDeveloper(_logger, string.Format("RenderContents(), dtDest.DefaultView.Count={0}, dtDest.DefaultView.Table.Columns.Count={1}", sourceDataTable.DefaultView.Count, sourceDataTable.DefaultView.Table.Columns.Count));
                //foreach (DataColumn objDataColumnTmp in sourceDataTable.DefaultView.Table.Columns)
                //{
                //    MyTraceToDeveloper(_logger, string.Format("RenderContents(), dtDest.DefaultView.TableColumnName={0}, DataType={1}", objDataColumnTmp.ColumnName, objDataColumnTmp.DataType));
                //}

                myDataTable = new DataTableWrapper(sourceDataTable);
                Type t = myDataTable.GetType();
                myDataSource.TypeName = t.AssemblyQualifiedName;

                configureGridViewFilter();

                this.gView.DataBind();
            }
            catch (Exception ex)
            {
                MyLogToOperations(_logger, ex);

                throw;
            }
        }

        public void gView_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();
            MyTraceToDeveloper(_logger, string.Format("OnViewPageChanging(), e.NewPageIndex={0}, gView.PageIndex={1}", e.NewPageIndex, gView.PageIndex));

            gView.PageIndex = e.NewPageIndex;
            gView.DataBind();
        }

        public void gView_Sorting(object sender, GridViewSortEventArgs e)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();
            MyTraceToDeveloper(_logger, string.Format("gView_Sorting(), ViewState['SortExpression']={0}, ViewState['SortDirection']={1}, ViewState['FilterExpression']={2}",
                ViewState["SortExpression"], ViewState["SortDirection"], ViewState["FilterExpression"]));

            string lastExpression = "";
            if (ViewState["SortExpression"] != null)
                lastExpression = ViewState["SortExpression"].ToString();

            string lastDirection = "asc";
            if (ViewState["SortDirection"] != null)
                lastDirection = ViewState["SortDirection"].ToString();

            string newDirection = "asc";
            if (e.SortExpression.Equals(lastExpression, StringComparison.InvariantCultureIgnoreCase))
                newDirection = (lastDirection.Equals("asc", StringComparison.InvariantCultureIgnoreCase)) ? "desc" : "asc";

            MyTraceToDeveloper(_logger, string.Format("lastDirection={0}, newDirection={1}", lastDirection, newDirection));

            ViewState["SortExpression"] = e.SortExpression;
            ViewState["SortDirection"] = newDirection;

            //oView.Sort = e.SortExpression + " " + newDirection;

            if (ViewState["FilterExpression"] != null)
            {
                myDataSource.FilterExpression = (string)ViewState["FilterExpression"];
            }

            //gView.DataSource = oView;

            MyTraceToDeveloper(_logger, string.Format("myDataSource.SelectParameters.Count={0}, SortExpression={1}", myDataSource.SelectParameters.Count, e.SortExpression + " " + newDirection));
            myDataSource.SelectParameters["SortExpression"].DefaultValue = e.SortExpression + " " + newDirection;
            MyTraceToDeveloper(_logger, string.Format("000"));
        }
    }
}
